<!DOCTYPE html>
<html>
  <head>
  <meta http-equiv="content-type" content="text/html; charset=utf-8">
  <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport">
  <meta name="description" content="along&#39;s blog">
  <meta name="keyword" content="hexo-theme, vuejs">
  
    <link rel="shortcut icon" href="/css/images/logo.png">
  
  <title>
    
      react 性能优化 | ALONG
    
  </title>
  <link href="/cdn.along/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
  <link href="/cdn.along/nprogress/0.2.0/nprogress.min.css" rel="stylesheet">
  <link href="/cdn.along/highlight.js/9.12.0/styles/tomorrow.min.css" rel="stylesheet">
  
<link rel="stylesheet" href="/css/style.css">

  
  <script src="/cdn.along/jquery/3.2.1/jquery.min.js"></script>
  <script src="/cdn.along/geopattern/1.2.3/js/geopattern.min.js"></script>
  <script src="/cdn.along/nprogress/0.2.0/nprogress.min.js"></script>
  
    
<script src="/js/qrious.js"></script>

  
  
  
  
    <!-- MathJax support START -->
    <script type="text/x-mathjax-config">
      MathJax.Hub.Config({
        tex2jax: {
          inlineMath: [ ['$','$'], ["\\(","\\)"]  ],
          processEscapes: true,
          skipTags: ['script', 'noscript', 'style', 'textarea', 'pre', 'code']
        }
      });
    </script>

    <script type="text/x-mathjax-config">
      MathJax.Hub.Queue(function() {
        var all = MathJax.Hub.getAllJax(), i;
        for (i=0; i < all.length; i += 1) {
          all[i].SourceElement().parentNode.className += ' has-jax';
        }
      });
    </script>
    <script type="text/javascript" src="/cdn.along/mathjax/2.7.5/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
    <!-- MathJax support END -->
  


  
  
    
<script src="/js/local-search.js"></script>


<meta name="generator" content="Hexo 5.4.0"></head>
<div class="wechat-share">
  <img src="/css/images/logo.png" />
</div>
  <body>
    <header class="header fixed-header">
  <div class="header-container">
    <a class="home-link" href="/">
      <div class="logo"></div>
      <span>ALONG</span>
    </a>
    <ul class="right-list">
      
        <li class="list-item">
          
            <a href="/" class="item-link">Home</a>
          
        </li>
      
        <li class="list-item">
          
            <a href="/tags/" class="item-link">Tags</a>
          
        </li>
      
        <li class="list-item">
          
            <a href="/archives/" class="item-link">Archives</a>
          
        </li>
      
        <li class="list-item">
          
            <a href="/about/" class="item-link">About</a>
          
        </li>
      
      
        <li class="menu-item menu-item-search right-list">
    <a role="button" class="popup-trigger">
        <i class="fa fa-search fa-fw"></i>
    </a>
</li>
      
    </ul>
    <div class="menu">
      <span class="icon-bar"></span>
      <span class="icon-bar"></span>
      <span class="icon-bar"></span>
    </div>
    <div class="menu-mask">
      <ul class="menu-list">
        
          <li class="menu-item">
            
              <a href="/" class="menu-link">Home</a>
            
          </li>
        
          <li class="menu-item">
            
              <a href="/tags/" class="menu-link">Tags</a>
            
          </li>
        
          <li class="menu-item">
            
              <a href="/archives/" class="menu-link">Archives</a>
            
          </li>
        
          <li class="menu-item">
            
              <a href="/about/" class="menu-link">About</a>
            
          </li>
        
      </ul>
    </div>
    
      <div class="search-pop-overlay">
    <div class="popup search-popup">
        <div class="search-header">
            <span class="search-icon">
                <i class="fa fa-search"></i>
            </span>
            <div class="search-input-container">
                <input autocomplete="off" autocapitalize="off"
                    placeholder="Please enter your keyword(s) to search." spellcheck="false"
                    type="search" class="search-input">
            </div>
            <span class="popup-btn-close">
                <i class="fa fa-times-circle"></i>
            </span>
        </div>
        <div id="search-result">
            <div id="no-result">
                <i class="fa fa-spinner fa-pulse fa-5x fa-fw"></i>
            </div>
        </div>
    </div>
</div>
    
  </div>
</header>

    <div id="article-banner">
  <h2>react 性能优化</h2>
  <p class="post-date">2021-01-20</p>
  <div class="arrow-down">
    <a href="javascript:;"></a>
  </div>
</div>
<main class="app-body flex-box">
  <!-- Article START -->
  <article class="post-article">
    <section class="markdown-content"><h3 id="React-性能优化"><a href="#React-性能优化" class="headerlink" title="React 性能优化"></a>React 性能优化</h3><p>核心减少渲染真实DOM的频率,减少Diff比对次数</p>
<h4 id="1-组件卸载前做清理操作"><a href="#1-组件卸载前做清理操作" class="headerlink" title="1. 组件卸载前做清理操作"></a>1. 组件卸载前做清理操作</h4><p>组建中注册的事件计时器等在组件卸载时做清理操作</p>
<h4 id="2-使用纯组件降低组件重新渲染的频率"><a href="#2-使用纯组件降低组件重新渲染的频率" class="headerlink" title="2. 使用纯组件降低组件重新渲染的频率"></a>2. 使用纯组件降低组件重新渲染的频率</h4><p>纯组件指在输入相同的state props 时呈现相同的输出</p>
<ul>
<li><strong>PureComponent</strong> 内部通过对当props和state进行浅比较，减少不必要的diff<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Com</span> <span class="keyword">extends</span> <span class="title">React</span>.<span class="title">PureComponent</span> </span>&#123;</span><br><span class="line">	...</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li>
<li>也可以通过生命周期函数 <strong>shouComponentUpdate</strong> 来阻止组件不必要的渲染</li>
</ul>
<h4 id="3-React-memo"><a href="#3-React-memo" class="headerlink" title="3. React.memo"></a>3. React.memo</h4><p>用于函数组件，类似类组件使用的 <strong>PureComponent</strong></p>
<p><strong>React.memo</strong> 是一个高阶组件（HOC， 高阶组件用于共享代码，逻辑复用）</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> MemoCon = React.memo(<span class="function">(<span class="params">props</span>) =&gt;</span> &#123;</span><br><span class="line">	<span class="keyword">return</span> <span class="xml"><span class="tag">&lt;<span class="name">div</span>&gt;</span>&#123;props.name&#125;<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line"><span class="comment">// 使用 &lt;MemoCon&gt;时 只要name不变就不会重新渲染</span></span><br></pre></td></tr></table></figure>

<p><strong>memo</strong> 也可以通过传递第二个参数，来进行深度比较</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Name</span>(<span class="params">props</span>) </span>&#123;</span><br><span class="line">	<span class="keyword">return</span> <span class="xml"><span class="tag">&lt;<span class="name">div</span>&gt;</span>&#123;props.obj.name&#125;<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> MemoCon = React.memo(Name, <span class="function">(<span class="params">preProps, newProps</span>) =&gt;</span> &#123;</span><br><span class="line">	<span class="keyword">if</span> (preProps.name === newProps.name) &#123;</span><br><span class="line">		<span class="keyword">return</span> <span class="literal">true</span>; <span class="comment">// 返回 true 代表不用更新</span></span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	<span class="keyword">return</span> <span class="literal">false</span>; <span class="comment">// 返回false 代表需要更新</span></span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>

<h4 id="4-shouComponentUpdate-减少组件渲染频率"><a href="#4-shouComponentUpdate-减少组件渲染频率" class="headerlink" title="4. shouComponentUpdate 减少组件渲染频率"></a>4. shouComponentUpdate 减少组件渲染频率</h4><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Con</span> <span class="keyword">extends</span> <span class="title">Component</span> </span>&#123;</span><br><span class="line">	shouldComponentUpdate(nextProps, nextState) &#123;</span><br><span class="line">		<span class="keyword">if</span> (<span class="built_in">this</span>.state.name !== nextState.name) &#123;</span><br><span class="line">			<span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">		&#125; <span class="keyword">else</span> <span class="keyword">return</span> <span class="literal">false</span></span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	...</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="5-懒加载"><a href="#5-懒加载" class="headerlink" title="5.懒加载"></a>5.懒加载</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">const &#123;lazy, Suspense&#125; from &#39;react&#39;;</span><br><span class="line"></span><br><span class="line">const About &#x3D; lazy(() &#x3D;&gt; import(&#39;.&#x2F;About&#39;));</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">&lt;BrowserRouter&gt;</span><br><span class="line">	&lt;Switch&gt;</span><br><span class="line">		&lt;Route path&#x3D;&quot;&#x2F;about&quot;&gt;</span><br><span class="line">			&lt;Suspense fallback&#x3D;&#123;&lt;div&gt;loading...&lt;&#x2F;div&gt;&#125;&gt;</span><br><span class="line">				&lt;About&#x2F;&gt;</span><br><span class="line">			&lt;&#x2F;Suspense&gt;</span><br><span class="line">		&lt;&#x2F;Route&gt;</span><br><span class="line">	&lt;&#x2F;Switch&gt;</span><br><span class="line">&lt;&#x2F;BrowserRouter&gt;</span><br></pre></td></tr></table></figure>

<h4 id="6-Fragment-来避免额外的标记"><a href="#6-Fragment-来避免额外的标记" class="headerlink" title="6. Fragment 来避免额外的标记"></a>6. Fragment 来避免额外的标记</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">&lt;React.Fragment&gt;</span><br><span class="line">	&lt;div&gt;1&lt;&#x2F;div&gt;</span><br><span class="line">	&lt;div&gt;1&lt;&#x2F;div&gt;</span><br><span class="line">&lt;&#x2F;React.Fragment&gt;</span><br><span class="line"></span><br><span class="line">&#x2F;&#x2F; 或者直接</span><br><span class="line">&lt;&gt;</span><br><span class="line">	&lt;div&gt;1&lt;&#x2F;div&gt;</span><br><span class="line">	&lt;div&gt;1&lt;&#x2F;div&gt;</span><br><span class="line">&lt;&#x2F;&gt;</span><br></pre></td></tr></table></figure>

<h4 id="7-不要使用内联函数定义"><a href="#7-不要使用内联函数定义" class="headerlink" title="7. 不要使用内联函数定义"></a>7. 不要使用内联函数定义</h4><p>在使用内联函数后， <strong>render</strong> 每次运行都会创建函数的新实例,造成性能开销</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">&#x2F;&#x2F; 内联函数方式</span><br><span class="line">class Con extends Component &#123;</span><br><span class="line"></span><br><span class="line">	render () &#123;</span><br><span class="line">		return &lt;input</span><br><span class="line">			onChange&#x3D;&#123;e &#x3D;&gt; &#123;console.log(e.target.value)&#125;&#125;</span><br><span class="line">		&#x2F;&gt;</span><br><span class="line">	&#125;</span><br><span class="line">	</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">&#x2F;&#x2F;推荐这样写</span><br><span class="line">class Con extends Component &#123;</span><br><span class="line"></span><br><span class="line">	log &#x3D; (e) &#x3D;&gt; &#123;</span><br><span class="line">		console.log(e.target.value)</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	render () &#123;</span><br><span class="line">		return &lt;input</span><br><span class="line">			onChange&#x3D;&#123;this.log&#125;</span><br><span class="line">		&#x2F;&gt;</span><br><span class="line">	&#125;</span><br><span class="line">	</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h4 id="8-在构造函数中this绑定"><a href="#8-在构造函数中this绑定" class="headerlink" title="8. 在构造函数中this绑定"></a>8. 在构造函数中this绑定</h4><p>通过 <strong>fn(){}</strong> 的形式声明函数时，可以通过在构造函数中绑定 <strong>this</strong> 也可以通过调用的地方绑定 <strong>this</strong>,不过两者的方式也存在区别</p>
<p>在 调用的地方 绑定 <strong>this</strong> 会造成与内联函数一样的问题，每次调用 render 都会生成一个新的函数实例，从而产生性能问题，（并且会影响子组件里的 <strong>componentDidUpdate</strong>失效 ）</p>
<p>而 <strong>constroctor</strong> 中执行会只绑定一次，推荐使用这种用法</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;&#x2F; 不推荐</span><br><span class="line">class Con extends Component &#123;</span><br><span class="line">	constructor(props) &#123;&#125;</span><br><span class="line">	</span><br><span class="line">	fn() &#123;&#125;</span><br><span class="line">	</span><br><span class="line">	render() &#123;</span><br><span class="line">		return &lt;button onClick&#x3D;&#123;this.fn.bind(this)&#125;&gt;click&lt;&#x2F;button&gt;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">&#x2F;&#x2F; 推荐</span><br><span class="line">class Con extends Component &#123;</span><br><span class="line">	constructor(props) &#123;</span><br><span class="line">        super(props);</span><br><span class="line">        this.fn &#x3D; this.fn.bind(this);</span><br><span class="line">    &#125;</span><br><span class="line">	</span><br><span class="line">	fn() &#123;&#125;</span><br><span class="line">	</span><br><span class="line">	render() &#123;</span><br><span class="line">		return &lt;button onClick&#x3D;&#123;this.fn&#125;&gt;click&lt;&#x2F;button&gt;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>当然，我们也可以借助箭头函数来书写，这里看下箭头函数编译后的结果</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Con</span> <span class="keyword">extends</span> <span class="title">Component</span> </span>&#123;</span><br><span class="line">	fn = <span class="function">() =&gt;</span> &#123;</span><br><span class="line">		<span class="built_in">console</span>.log(<span class="string">&#x27;fn&#x27;</span>);</span><br><span class="line">	&#125;</span><br><span class="line">	...</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 编译后相当于</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Con</span> <span class="keyword">extends</span> <span class="title">Component</span> </span>&#123;</span><br><span class="line">    <span class="keyword">constructor</span>(props) &#123;</span><br><span class="line">        <span class="built_in">super</span>(props)</span><br><span class="line">        <span class="built_in">this</span>.fn = <span class="function">() =&gt;</span> &#123;</span><br><span class="line">            <span class="built_in">console</span>.log(<span class="string">&#x27;fn&#x27;</span>)</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h4 id="9-箭头函数使用情景"><a href="#9-箭头函数使用情景" class="headerlink" title="9. 箭头函数使用情景"></a>9. 箭头函数使用情景</h4><p>箭头函数在this指向上有一定优势， 但是也有不利的一面</p>
<p>箭头函数会将函数绑定到实例对象上，添加的是实例对象属性， 而不是原型对象属性，如果组件多次调用，每个组件实例对象上都会有相同的函数实例，会产生一定的性能开销</p>
<p>那么在构造函数中绑定 <strong>this</strong> 不也是实例对象属性吗，没错。上面一点我们也看过箭头函数编译后的代码了。不过这里需要探讨的是，在什么情况下更适合使用箭头函数，什么情况下更适合使用普通函数。</p>
<p>这里举一个栗子, 场景是我们有一个组件，需要从接口获取公司人员的数组，数组中的每一个人包含id，所属领导id等信息，现在在这个组件中需要将数组处理成一个树形的包含关系，在界面上显示一个包含层级关系的公司员工列表。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br></pre></td><td class="code"><pre><span class="line">class Con extends Component &#123;</span><br><span class="line">	constructor(props) &#123;</span><br><span class="line">		super(props);</span><br><span class="line">		this.state &#x3D; &#123;</span><br><span class="line">			peopletree: []</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">	componentDidMount() &#123;</span><br><span class="line">		&#x2F;&#x2F; 模拟从服务器获取到了数据 data， 代表公司的所有人员集合</span><br><span class="line">		const data &#x3D; [</span><br><span class="line">				&#123;</span><br><span class="line">					belong: null,</span><br><span class="line">					id: &#39;1&#39;,</span><br><span class="line">					name: &#39;张三&#39;,</span><br><span class="line">					position: &#39;部门总监&#39;,</span><br><span class="line">				&#125;,</span><br><span class="line">				&#123;</span><br><span class="line">					belong: &#39;1&#39;,</span><br><span class="line">					id: &#39;2&#39;,</span><br><span class="line">					name: &#39;李四&#39;,</span><br><span class="line">					position: &#39;前端leader&#39;</span><br><span class="line">				&#125;,</span><br><span class="line">				&#x2F;&#x2F; ...</span><br><span class="line">			]</span><br><span class="line">		&#125;</span><br><span class="line">    	&#x2F;&#x2F; 调用实例方法</span><br><span class="line">		this.setPeopleTree(data);</span><br><span class="line">	&#125;</span><br><span class="line">	</span><br><span class="line">	setPeopleTree &#x3D; (list) &#x3D;&gt; &#123;</span><br><span class="line">        &#x2F;&#x2F; 使用原型属性方法拿到结果</span><br><span class="line">		const peopletree &#x3D; this.reduceListToTreeList(list);</span><br><span class="line">        this.setState(&#123;</span><br><span class="line">            peopletree</span><br><span class="line">        &#125;)</span><br><span class="line">	&#125;</span><br><span class="line">	</span><br><span class="line">	reduceListToTreeList(list) &#123;</span><br><span class="line">        &#x2F;&#x2F;处理逻辑 省略</span><br><span class="line">		&#x2F;&#x2F; 这里直接模拟返回处理完成的结果</span><br><span class="line">		return [&#123;</span><br><span class="line">            &#123;</span><br><span class="line">                belong: null,</span><br><span class="line">                id: &#39;1&#39;,</span><br><span class="line">                name: &#39;张三&#39;,</span><br><span class="line">                position: &#39;部门总监&#39;,</span><br><span class="line">            	under: [</span><br><span class="line">            		&#123;</span><br><span class="line">            			belong: &#39;1&#39;,</span><br><span class="line">                         id: &#39;2&#39;,</span><br><span class="line">                         name: &#39;李四&#39;,</span><br><span class="line">                         position: &#39;前端leader&#39;,</span><br><span class="line">            			under: [...]</span><br><span class="line">        			&#125;</span><br><span class="line">            	]</span><br><span class="line">            &#125;,</span><br><span class="line">        &#125;]</span><br><span class="line">	&#125;</span><br><span class="line">    </span><br><span class="line">    render() &#123;</span><br><span class="line">        ... &#x2F;&#x2F; 渲染界面</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>这个栗子中，通过 处理列表返回树的方法 <strong>reduceListToTreeList</strong> 由于内部不需要使用 <strong>this</strong>， 通过普通函数声明方式将其挂载到组件原型属性上，不必在每个实例声明相同逻辑的函数，减少一定的性能开销</p>
<p>所以，在类组件里的某些不使用this的函数中，可以使用普通函数的声明方法挂载到原型对象属性上。（ps: 当然了，如果有需要也可以把原型属性方法提取到工具类里使用）</p>
<h4 id="10-避免使用内联样式属性"><a href="#10-避免使用内联样式属性" class="headerlink" title="10. 避免使用内联样式属性"></a>10. 避免使用内联样式属性</h4><p>内联样式会被编译成js代码，然后映射上元素上。需要额外执行js脚本，需要浪费一些性能。</p>
<p>另外，通过内联样式也会导致组件每次render都会实例化一个样式对象，产生一定的开销。如果一定要使用内联js样式，尽量提取样式对象到外层吧。</p>
<p>推荐使用引入 <strong>css</strong> 文件的方式。</p>
<p>ps：这里再提一种非常少见也是错误使用的方法，比如在调用一个 <strong>memo</strong> 优化后的组件，给这个组件传递了 <strong>style</strong> （react是不允许使用style作为属性传递的，如果在组件内部获取 <strong>props.style</strong> 会报错。但是如果内部没有这么做，仅仅是父组件在调用 <strong>memo</strong> 优化的组件时传递了 内联 <strong>style</strong> 是不会报错的），那么每次父组件<strong>render</strong> ， 子组件都会<strong>render</strong>。 </p>
<p>通过这点只是为了提示大家在<strong>render</strong>中尽量不要动态的声明对象、函数。因为</p>
<ul>
<li>每次都要声明新的对象，之前的对象浏览器又要额外做垃圾回收。</li>
<li>会导致接收对象参数的 纯组件 无谓的渲染</li>
</ul>
<h4 id="11-优化条件渲染"><a href="#11-优化条件渲染" class="headerlink" title="11. 优化条件渲染"></a>11. 优化条件渲染</h4><p>频繁的挂载卸载组建是消耗性能的操作，因此需要减少挂载和卸载次数</p>
<p>在 <strong>React</strong> 中经常通过条件来渲染不同的界面</p>
<p>比如这里我有一个经过memo优化的组件 <strong>MemoFooter</strong> 和一个普通组件 <strong>Header</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">function Header () &#123;</span><br><span class="line">	useEffect(() &#x3D;&gt; &#123;</span><br><span class="line">		console.log(&#39;header挂载&#39;)</span><br><span class="line">		return () &#x3D;&gt; &#123;</span><br><span class="line">			console.log(&#39;header卸载&#39;);</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;)</span><br><span class="line">	return &lt;div&gt;header&lt;&#x2F;div&gt;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">function Footer () &#123;</span><br><span class="line">	useEffect(() &#x3D;&gt; &#123;</span><br><span class="line">		console.log(&#39;footer挂载&#39;);</span><br><span class="line">		return () &#x3D;&gt; &#123;</span><br><span class="line">			console.log(&#39;footer卸载&#39;)</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;)</span><br><span class="line">	return &lt;div&gt;footer&lt;&#x2F;div&gt;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">const MemoFooter &#x3D; React.memo(Footer);</span><br></pre></td></tr></table></figure>

<p>然后在 <strong>App</strong> 组件中条件渲染 <strong>Header</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">function App () &#123;</span><br><span class="line">	const [staff, setStaff] &#x3D; useState(false);</span><br><span class="line">	useEffect(() &#x3D;&gt; &#123;</span><br><span class="line">		setTimeout(() &#x3D;&gt; &#123;</span><br><span class="line">			setStaff(true);</span><br><span class="line">		&#125;, 5000)</span><br><span class="line">	&#125;, [])</span><br><span class="line"></span><br><span class="line">	if (staff) &#123;</span><br><span class="line">		return &lt;&gt;</span><br><span class="line">			&lt;Header&#x2F;&gt;</span><br><span class="line">			&lt;MemoFooter&#x2F;&gt;</span><br><span class="line">		&lt;&#x2F;&gt;</span><br><span class="line">	&#125; else &#123;</span><br><span class="line">		return &lt;&gt;</span><br><span class="line">			&lt;MemoFooter&#x2F;&gt;</span><br><span class="line">		&lt;&#x2F;&gt;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>在上面的情况中，五秒后会看到控制台打印</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">footer挂载</span><br><span class="line">&#x2F;&#x2F; 5s 后</span><br><span class="line">footer卸载</span><br><span class="line">header挂载</span><br><span class="line">footer挂载</span><br></pre></td></tr></table></figure>

<p>推荐优化条件语句</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">function App () &#123;</span><br><span class="line">	const [staff, setStaff] &#x3D; useState(false);</span><br><span class="line">	useEffect(() &#x3D;&gt; &#123;</span><br><span class="line">		setTimeout(() &#x3D;&gt; &#123;</span><br><span class="line">			setStaff(true);</span><br><span class="line">		&#125;, 5000)</span><br><span class="line">	&#125;, [])</span><br><span class="line"></span><br><span class="line">	return &lt;&gt;</span><br><span class="line">	 	&#123; staff &amp;&amp; &lt;Header&#x2F;&gt; &#125;</span><br><span class="line">	 	&lt;MemoFooter&#x2F;&gt;</span><br><span class="line">	&lt;&#x2F;&gt;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>优化后 控制台打印情况为</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">footer挂载</span><br><span class="line">&#x2F;&#x2F; 5s后</span><br><span class="line">header挂载</span><br></pre></td></tr></table></figure>



<h4 id="12-不要在render中更改应用程序的状态"><a href="#12-不要在render中更改应用程序的状态" class="headerlink" title="12. 不要在render中更改应用程序的状态"></a>12. 不要在render中更改应用程序的状态</h4><p><strong>render</strong>中继续使用 更改程序状态，就会发生 <strong>render</strong> 方法无限调用导致程序崩溃</p>
<p>render中</p>
<ul>
<li>不要使用 <strong>setState</strong></li>
<li>不要通过其他手段查询更改原生 <strong>DOM</strong> 元素</li>
</ul>
<h4 id="13-为组件创建错误边界"><a href="#13-为组件创建错误边界" class="headerlink" title="13. 为组件创建错误边界"></a>13. 为组件创建错误边界</h4><p>默认情况下组件错误会导致整个应用程序中断，创建错误便捷确保在特定组建发生错误时程序不会中断</p>
<p>错误边界可以捕获子组件在渲染时发生的错误，当错误发生时，将错误记录下来，并可以显示备用UI界面</p>
<p>错误边界涉及两个生命周期函数</p>
<ul>
<li>getDerivedStateFromError， 静态方法，返回一个对象，该对象会和state进行合并，用于更改应用程序状态 </li>
<li>componentDidCatch，用于记录应用程序错误信息，该方法的参数就是错误对象</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">function Child() &#123;</span><br><span class="line">	throw new Error(&#39;Child 内部渲染出 错了&#39;)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">class App extends React.Component &#123;</span><br><span class="line">	constructor(props) &#123;</span><br><span class="line">		super(props);</span><br><span class="line">		this.state &#x3D;&#123;</span><br><span class="line">			error: false</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">	componentDidCatch(e) &#123;</span><br><span class="line">		console.log(e.message, &#39;发送请求服务器记录错误日志&#39;)</span><br><span class="line">	&#125;</span><br><span class="line">	static getDerivedStateFromError(e) &#123;</span><br><span class="line">		return &#123;</span><br><span class="line">			error: e</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">	render() &#123;</span><br><span class="line">		const &#123;error&#125; &#x3D; this.state;</span><br><span class="line">		return error ? &lt;&gt;阿偶，出错了: &#123;error.message&#125;&lt;&#x2F;&gt; : &lt;Child&#x2F;&gt; </span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>当<strong>App</strong>组件渲染后，由于<strong>Child</strong>内部错误，<strong>App</strong>中会捕获到<strong>Child</strong>中的异常，调用 <strong>componentDidCatch</strong> 中的方法，并渲染错误替代界面。</p>
<p>由于是开发模式并使用了<strong>create-react-app</strong>，会看到这个界面，</p>
<img src="/2021/01/20/react-%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96/image-20210121112546301.png" class="">
<p><img src="./react-%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96/image-20210121112546301.png" alt="image-20210121112546301"></p>
<p>生产环境下，可以直接看到替代界面</p>
<img src="/2021/01/20/react-%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96/image-20210121112833454.png" class="">
<p><img src="./react-%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96/image-20210121112833454.png" alt="image-20210121112833454"></p>
<h4 id="14-避免数据结构突变"><a href="#14-避免数据结构突变" class="headerlink" title="14. 避免数据结构突变"></a>14. 避免数据结构突变</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">this.state &#x3D; &#123;</span><br><span class="line">	name: &#39;along&#39;,</span><br><span class="line">	age: 12,</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">render () &#123;</span><br><span class="line">	return &lt;div&gt;</span><br><span class="line">		&#123;this.state.name&#125;</span><br><span class="line">		&#123;this.state.age&#125;</span><br><span class="line">	&lt;&#x2F;div&gt;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h4 id="15-为列表数据添加唯一标识key"><a href="#15-为列表数据添加唯一标识key" class="headerlink" title="15. 为列表数据添加唯一标识key"></a>15. 为列表数据添加唯一标识key</h4><p>添加唯一标识来优化遍历节点的<strong>diff</strong>性能,这有利于<strong>react</strong>内部优化</p>
<h4 id="16-节流和防抖"><a href="#16-节流和防抖" class="headerlink" title="16. 节流和防抖"></a>16. 节流和防抖</h4><p>节流限制频率，防抖限制连续</p>
<p>react中的一些场景如果没有进行节流防抖会导致多次的无效的render</p>
<p>节流</p>
<ul>
<li>下拉加载</li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">throttle</span>(<span class="params">fn, time</span>) </span>&#123;</span><br><span class="line">	<span class="keyword">let</span> canRun = <span class="literal">true</span>;</span><br><span class="line">	<span class="keyword">return</span> <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">		<span class="keyword">if</span> (!canRun) <span class="keyword">return</span>;</span><br><span class="line">		canRun = <span class="literal">false</span>;</span><br><span class="line">		</span><br><span class="line">		<span class="built_in">setTimeout</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">            fn.apply(<span class="built_in">this</span>, ...arguments);</span><br><span class="line">			canRun = <span class="literal">true</span>;</span><br><span class="line">		&#125;, time)</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<p>防抖， 只在一段操作的最后执行操作</p>
<ul>
<li>关键字提示</li>
<li>wendow.onResize, </li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">debounce</span> (<span class="params">fn, time</span>) </span>&#123;</span><br><span class="line">	<span class="keyword">let</span> timer = <span class="literal">null</span>;</span><br><span class="line">	<span class="keyword">return</span> <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">		<span class="built_in">clearInterval</span>(timer);</span><br><span class="line">		<span class="built_in">setTimeout</span>(fn, time);</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="17-外部使用-CDN-加载"><a href="#17-外部使用-CDN-加载" class="headerlink" title="17. 外部使用 CDN 加载"></a>17. 外部使用 CDN 加载</h4><p>内容交付网络 （CDN）, 指得是地理上分散的服务器组，他们提供网络内容的快速交付</p>
<p>好处</p>
<ul>
<li>突破浏览器对同一域下并发请求的数量限制，可以将不同的资源放到不同的CDN中</li>
<li>当你向CDN发送请求是，会通过理你最近的数据中心进行相应，减少延迟</li>
<li>多个网站引用的相同资源会有缓存，比如之前网站缓存了 <strong>jquery</strong></li>
</ul>
<h4 id="18-依赖优化"><a href="#18-依赖优化" class="headerlink" title="18. 依赖优化"></a>18. 依赖优化</h4><p>项目中以来的第三方包，但是没有使用包中的所有代码，可以通过插件对以来进行优化，比如<strong>antd</strong>的按需引入</p>
<h4 id="19-长列表优化（虚拟列表）"><a href="#19-长列表优化（虚拟列表）" class="headerlink" title="19. 长列表优化（虚拟列表）"></a>19. 长列表优化（虚拟列表）</h4><p>在渲染大数据量的列表时，如果一层行全部渲染会感到明显的卡顿。</p>
<p>此时我们可以 通过 <strong>可视区渲染</strong> 来提升性能，即只渲染页面可视区域及附近的列表项，在滚动列表时动态更新列表项 </p>
<p>在<strong>react</strong>中可以借助<strong>react-virtualized</strong> 来进行 <strong>可视区渲染</strong></p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 用于渲染每一行的内容</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">rowRenderer</span>(<span class="params">&#123;</span></span></span><br><span class="line"><span class="function"><span class="params">	key,         <span class="regexp">//</span> <span class="regexp">//</span> 唯一key，这个是组件帮我们生成的</span></span></span><br><span class="line"><span class="function"><span class="params">	index,       <span class="regexp">//</span> 索引号</span></span></span><br><span class="line"><span class="function"><span class="params">	isScrolling, <span class="regexp">//</span> 当前项是否正在滚动中</span></span></span><br><span class="line"><span class="function"><span class="params">	isVisible,   <span class="regexp">//</span> 当前项在List中是否可见的</span></span></span><br><span class="line"><span class="function"><span class="params">	style        <span class="regexp">//</span> 给每一个行数添加该样式,包含了定位信息</span></span></span><br><span class="line"><span class="function"><span class="params">&#125;</span>) </span>&#123;</span><br><span class="line">	<span class="keyword">return</span> (</span><br><span class="line">		&lt;div</span><br><span class="line">			key=&#123;key&#125;</span><br><span class="line">			style=&#123;style&#125;</span><br><span class="line">		&gt;</span><br><span class="line">			&#123;list[index]&#125;</span><br><span class="line">		&lt;/div&gt;</span><br><span class="line">	)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">App</span> <span class="keyword">extends</span> <span class="title">React</span>.<span class="title">Component</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">	</span><br><span class="line">	render() &#123;</span><br><span class="line">		<span class="keyword">const</span> list = [...]; <span class="comment">// 一个大数据列表</span></span><br><span class="line"></span><br><span class="line">		<span class="keyword">return</span> <span class="xml"><span class="tag">&lt;<span class="name">List</span></span></span></span><br><span class="line"><span class="xml">			// 组件的宽度</span></span><br><span class="line"><span class="xml">			width=&#123;300&#125;</span></span><br><span class="line"><span class="xml">			// 组件的高度</span></span><br><span class="line"><span class="xml">			height=&#123;50&#125;</span></span><br><span class="line"><span class="xml">			rowCount=&#123;list.length&#125;</span></span><br><span class="line"><span class="xml">			// 每行的高度</span></span><br><span class="line"><span class="xml">			rowHeight=&#123;20&#125;</span></span><br><span class="line"><span class="xml">			rowRenderer=&#123;rowRenderer&#125;</span></span><br><span class="line"><span class="xml">		/&gt;</span></span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



</section>
    <!-- Tags START -->
    
      <div class="tags">
        <span>Tags:</span>
        
  <a href="/tags#react" >
    <span class="tag-code">react</span>
  </a>

  <a href="/tags#性能优化" >
    <span class="tag-code">性能优化</span>
  </a>

      </div>
    
    <!-- Tags END -->
    <!-- NAV START -->
    
  <div class="nav-container">
    <!-- reverse left and right to put prev and next in a more logic postition -->
    
      <a class="nav-left" href="/2021/01/20/react-hooks/">
        <span class="nav-arrow">← </span>
        
          react-hooks
        
      </a>
    
    
      <a class="nav-right" href="/2021/06/12/vue3-0%E8%AF%AD%E6%B3%95/">
        
          vue3语法
        
        <span class="nav-arrow"> →</span>
      </a>
    
  </div>

    <!-- NAV END -->
    <!-- 打赏 START -->
    
      <div class="money-like">
        <div class="reward-btn">
          赏
          <span class="money-code">
            <span class="alipay-code">
              <div class="code-image"></div>
              <b>使用支付宝打赏</b>
            </span>
            <span class="wechat-code">
              <div class="code-image"></div>
              <b>使用微信打赏</b>
            </span>
          </span>
        </div>
        <p class="notice">若你觉得我的文章对你有帮助，欢迎点击上方按钮对我打赏</p>
      </div>
    
    <!-- 打赏 END -->
    <!-- 二维码 START -->
    
      <div class="qrcode">
        <canvas id="share-qrcode"></canvas>
        <p class="notice">扫描二维码，分享此文章</p>
      </div>
    
    <!-- 二维码 END -->
    
      <!-- No Comment -->
    
  </article>
  <!-- Article END -->
  <!-- Catalog START -->
  
    <aside class="catalog-container">
  <div class="toc-main">
    <strong class="toc-title">Catalog</strong>
    
      <ol class="toc-nav"><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#React-%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96"><span class="toc-nav-text">React 性能优化</span></a><ol class="toc-nav-child"><li class="toc-nav-item toc-nav-level-4"><a class="toc-nav-link" href="#1-%E7%BB%84%E4%BB%B6%E5%8D%B8%E8%BD%BD%E5%89%8D%E5%81%9A%E6%B8%85%E7%90%86%E6%93%8D%E4%BD%9C"><span class="toc-nav-text">1. 组件卸载前做清理操作</span></a></li><li class="toc-nav-item toc-nav-level-4"><a class="toc-nav-link" href="#2-%E4%BD%BF%E7%94%A8%E7%BA%AF%E7%BB%84%E4%BB%B6%E9%99%8D%E4%BD%8E%E7%BB%84%E4%BB%B6%E9%87%8D%E6%96%B0%E6%B8%B2%E6%9F%93%E7%9A%84%E9%A2%91%E7%8E%87"><span class="toc-nav-text">2. 使用纯组件降低组件重新渲染的频率</span></a></li><li class="toc-nav-item toc-nav-level-4"><a class="toc-nav-link" href="#3-React-memo"><span class="toc-nav-text">3. React.memo</span></a></li><li class="toc-nav-item toc-nav-level-4"><a class="toc-nav-link" href="#4-shouComponentUpdate-%E5%87%8F%E5%B0%91%E7%BB%84%E4%BB%B6%E6%B8%B2%E6%9F%93%E9%A2%91%E7%8E%87"><span class="toc-nav-text">4. shouComponentUpdate 减少组件渲染频率</span></a></li><li class="toc-nav-item toc-nav-level-4"><a class="toc-nav-link" href="#5-%E6%87%92%E5%8A%A0%E8%BD%BD"><span class="toc-nav-text">5.懒加载</span></a></li><li class="toc-nav-item toc-nav-level-4"><a class="toc-nav-link" href="#6-Fragment-%E6%9D%A5%E9%81%BF%E5%85%8D%E9%A2%9D%E5%A4%96%E7%9A%84%E6%A0%87%E8%AE%B0"><span class="toc-nav-text">6. Fragment 来避免额外的标记</span></a></li><li class="toc-nav-item toc-nav-level-4"><a class="toc-nav-link" href="#7-%E4%B8%8D%E8%A6%81%E4%BD%BF%E7%94%A8%E5%86%85%E8%81%94%E5%87%BD%E6%95%B0%E5%AE%9A%E4%B9%89"><span class="toc-nav-text">7. 不要使用内联函数定义</span></a></li><li class="toc-nav-item toc-nav-level-4"><a class="toc-nav-link" href="#8-%E5%9C%A8%E6%9E%84%E9%80%A0%E5%87%BD%E6%95%B0%E4%B8%ADthis%E7%BB%91%E5%AE%9A"><span class="toc-nav-text">8. 在构造函数中this绑定</span></a></li><li class="toc-nav-item toc-nav-level-4"><a class="toc-nav-link" href="#9-%E7%AE%AD%E5%A4%B4%E5%87%BD%E6%95%B0%E4%BD%BF%E7%94%A8%E6%83%85%E6%99%AF"><span class="toc-nav-text">9. 箭头函数使用情景</span></a></li><li class="toc-nav-item toc-nav-level-4"><a class="toc-nav-link" href="#10-%E9%81%BF%E5%85%8D%E4%BD%BF%E7%94%A8%E5%86%85%E8%81%94%E6%A0%B7%E5%BC%8F%E5%B1%9E%E6%80%A7"><span class="toc-nav-text">10. 避免使用内联样式属性</span></a></li><li class="toc-nav-item toc-nav-level-4"><a class="toc-nav-link" href="#11-%E4%BC%98%E5%8C%96%E6%9D%A1%E4%BB%B6%E6%B8%B2%E6%9F%93"><span class="toc-nav-text">11. 优化条件渲染</span></a></li><li class="toc-nav-item toc-nav-level-4"><a class="toc-nav-link" href="#12-%E4%B8%8D%E8%A6%81%E5%9C%A8render%E4%B8%AD%E6%9B%B4%E6%94%B9%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F%E7%9A%84%E7%8A%B6%E6%80%81"><span class="toc-nav-text">12. 不要在render中更改应用程序的状态</span></a></li><li class="toc-nav-item toc-nav-level-4"><a class="toc-nav-link" href="#13-%E4%B8%BA%E7%BB%84%E4%BB%B6%E5%88%9B%E5%BB%BA%E9%94%99%E8%AF%AF%E8%BE%B9%E7%95%8C"><span class="toc-nav-text">13. 为组件创建错误边界</span></a></li><li class="toc-nav-item toc-nav-level-4"><a class="toc-nav-link" href="#14-%E9%81%BF%E5%85%8D%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E7%AA%81%E5%8F%98"><span class="toc-nav-text">14. 避免数据结构突变</span></a></li><li class="toc-nav-item toc-nav-level-4"><a class="toc-nav-link" href="#15-%E4%B8%BA%E5%88%97%E8%A1%A8%E6%95%B0%E6%8D%AE%E6%B7%BB%E5%8A%A0%E5%94%AF%E4%B8%80%E6%A0%87%E8%AF%86key"><span class="toc-nav-text">15. 为列表数据添加唯一标识key</span></a></li><li class="toc-nav-item toc-nav-level-4"><a class="toc-nav-link" href="#16-%E8%8A%82%E6%B5%81%E5%92%8C%E9%98%B2%E6%8A%96"><span class="toc-nav-text">16. 节流和防抖</span></a></li><li class="toc-nav-item toc-nav-level-4"><a class="toc-nav-link" href="#17-%E5%A4%96%E9%83%A8%E4%BD%BF%E7%94%A8-CDN-%E5%8A%A0%E8%BD%BD"><span class="toc-nav-text">17. 外部使用 CDN 加载</span></a></li><li class="toc-nav-item toc-nav-level-4"><a class="toc-nav-link" href="#18-%E4%BE%9D%E8%B5%96%E4%BC%98%E5%8C%96"><span class="toc-nav-text">18. 依赖优化</span></a></li><li class="toc-nav-item toc-nav-level-4"><a class="toc-nav-link" href="#19-%E9%95%BF%E5%88%97%E8%A1%A8%E4%BC%98%E5%8C%96%EF%BC%88%E8%99%9A%E6%8B%9F%E5%88%97%E8%A1%A8%EF%BC%89"><span class="toc-nav-text">19. 长列表优化（虚拟列表）</span></a></li></ol></li></ol>
    
  </div>
</aside>
  
  <!-- Catalog END -->
</main>

<script>
  (function () {
    var url = 'https://github.com/alongithub/2021/01/20/react-性能优化/';
    var banner = ''
    if (banner !== '' && banner !== 'undefined' && banner !== 'null') {
      $('#article-banner').css({
        'background-image': 'url(' + banner + ')'
      })
    } else {
      $('#article-banner').geopattern(url)
    }
    $('.header').removeClass('fixed-header')

    // error image
    $(".markdown-content img").on('error', function() {
      $(this).attr('src', '/css/images/error_icon.png')
      $(this).css({
        'cursor': 'default'
      })
    })

    // zoom image
    $(".markdown-content img").on('click', function() {
      var src = $(this).attr('src')
      if (src !== '/css/images/error_icon.png') {
        var imageW = $(this).width()
        var imageH = $(this).height()

        var zoom = ($(window).width() * 0.95 / imageW).toFixed(2)
        zoom = zoom < 1 ? 1 : zoom
        zoom = zoom > 2 ? 2 : zoom
        var transY = (($(window).height() - imageH) / 2).toFixed(2)

        $('body').append('<div class="image-view-wrap"><div class="image-view-inner"><img src="'+ src +'" /></div></div>')
        $('.image-view-wrap').addClass('wrap-active')
        $('.image-view-wrap img').css({
          'width': `${imageW}`,
          'transform': `translate3d(0, ${transY}px, 0) scale3d(${zoom}, ${zoom}, 1)`
        })
        $('html').css('overflow', 'hidden')

        $('.image-view-wrap').on('click', function() {
          $(this).remove()
          $('html').attr('style', '')
        })
      }
    })
  })();
</script>


  <script>
    var qr = new QRious({
      element: document.getElementById('share-qrcode'),
      value: document.location.href
    });
  </script>






    <div class="scroll-top">
  <span class="arrow-icon"></span>
</div>
    <footer class="app-footer">
  <p class="copyright">
    Copyright&copy; 2019-2022 along
    <br>
    <a href="https://beian.miit.gov.cn/" target="_blank">京ICP备2020044791号-1</a>
    <!-- <br>
    Theme by <a href="https://github.com/alongithub">alongithub</a>
     -->
  </p>
</footer>

<script>
  function async(u, c) {
    var d = document, t = 'script',
      o = d.createElement(t),
      s = d.getElementsByTagName(t)[0];
    o.src = u;
    if (c) { o.addEventListener('load', function (e) { c(null, e); }, false); }
    s.parentNode.insertBefore(o, s);
  }
</script>
<script>
  async("/cdn.along/fastclick/1.0.6/fastclick.min.js", function(){
    FastClick.attach(document.body);
  })
</script>

<script>
  var hasLine = 'true';
  async("/cdn.along/highlight.js/9.12.0/highlight.min.js", function(){
    $('figure pre').each(function(i, block) {
      var figure = $(this).parents('figure');
      if (hasLine === 'false') {
        figure.find('.gutter').hide();
      }
      hljs.configure({useBR: true});
      var lang = figure.attr('class').split(' ')[1] || 'code';
      var codeHtml = $(this).html();
      var codeTag = document.createElement('code');
      codeTag.className = lang;
      codeTag.innerHTML = codeHtml;
      $(this).attr('class', '').empty().html(codeTag);
      figure.attr('data-lang', lang.toUpperCase());
      hljs.highlightBlock(block);
    });
  })
</script>
<!-- Baidu Tongji -->


<script src="/js/script.js"></script>


  </body>
</html>